<?php

namespace Soen\Esign\Evidence\Adapter\Tp;

use Soen\Esign\Config;
use Soen\Esign\Evidence\Adapter\AdapterInterface;
use Soen\Esign\Exception\EviException;
use Soen\Esign\Http;
use think\Model;

class TpAdapter implements AdapterInterface
{
    public $http;
    public $config;
    /**
     * @var Model
     */
    public $evidenceCategoryModel;
    /**
     * @var Model
     */
    public $evidencePointModel;
    /**
     * @var Model
     */
    public $evidenceSceneModel;

    /**
     * @var Model
     */
    public $evidenceChainPointModel;

    /**
     * @var Model
     */
    public $evidenceChainModel;

    /**
     * @var Model
     */
    public $pointRow;
    /**
     * @var Model
     */
    public $sceneRow;
    /**
     * @var Model
     */
    public $currentChainModel;

    public function __construct(Http $http, Config $config, $models)
    {
        $this->http = $http;
        $this->config = $config;
        $this->evidenceCategoryModel = new $models['evidenceCategoryModel'];
        $this->evidencePointModel = new $models['evidencePointModel'];
        $this->evidenceSceneModel = new $models['evidenceSceneModel'];
        $this->evidenceChainPointModel = new $models['evidenceChainPointModel'];
        $this->evidenceChainModel = new $models['evidenceChainModel'];
    }

    public function evidenceMap()
    {
        $categoryCode = '';
        $sceneCode = '';
        $eviConfig = $this->config->getEviConfig();
        foreach ($eviConfig['evidence'] as $category) {
            $categoryArr[] = [
                'name'          =>  $category['name'],
                'category_code' =>  $category['category_code']
            ];
            $categoryCode = $category['category_code'];
            foreach ($category['scenes'] as $scene) {
                $sceneArr[] = [
                    'name'  =>  $scene['name'],
                    'scene_code'    =>  $scene['scene_code'],
                    'category_code' =>  $categoryCode,
                ];
                $sceneCode = $scene['scene_code'];
                foreach ($scene['points'] as $point) {
                    $pointArr[] = [
                        'type' => 0,
                        'scene_code' => $sceneCode,
                        'category_code' =>  $categoryCode,
                        'point_code' => $point['point_code'],
                        'name' => $point['name'],
                        'property' => $point['properties']
                    ];
                }
            }
        }
        //行业入库处理
        $categoryCodes= $this->evidenceCategoryModel->column('category_code');
        foreach ($categoryArr as $key => &$category) {
            if (in_array($category['category_code'], $categoryCodes)) {
                unset($categoryArr[$key]);
                continue;
            }
        }
        $this->evidenceCategoryModel->saveAll($categoryArr);
        //场景入库处理
        $sceneCodes= $this->evidenceSceneModel->column('scene_code');
        foreach ($sceneArr as $key => &$scene) {
            if (in_array($scene['scene_code'], $sceneCodes)) {
                unset($sceneArr[$key]);
                continue;
            }
        }
        $this->evidenceSceneModel->saveAll($sceneArr);
        //据点入库处理
        $pointCodes= $this->evidencePointModel->column('point_code');
        foreach ($pointArr as $key => &$point) {
            if (in_array($point['point_code'], $pointCodes)) {
                unset($pointArr[$key]);
                continue;
            }
        }
        $this->evidencePointModel->saveAll($pointArr);
    }

    public function setEsignCode()
    {
        //行业处理
        $evidenceCategories = $this->evidenceCategoryModel->where('e_category_code','')
            ->withoutField('create_time,update_time,delete_time')
            ->select();
        if(!$evidenceCategories->isEmpty()){
            $result = $this->http->post('busAdd', ['name' => $evidenceCategories->column('name')]);
            $resArr = array_flip($result['result']);
            foreach ($evidenceCategories as &$category){
                $category->e_category_code = $resArr[$category->name];
            }
            $this->evidenceCategoryModel->saveAll($evidenceCategories->toArray());
        }

        /*凭证名称(场景)处理*/
        $evidenceScenes = $this->evidenceSceneModel->where('e_scene_code','')
            ->withoutField('create_time,update_time,delete_time')
            ->select();
        $sceneBelongs = [];
        foreach ($evidenceScenes->toArray() as $scene){
            if(!isset($sceneBelongs[$scene['category_code']])){
                $sceneBelongs[$scene['category_code']] = [];
            }
            array_push($sceneBelongs[$scene['category_code']],$scene);
        }
        $eCategoryCodesColmun = $this->evidenceCategoryModel->whereIn('category_code',array_keys($sceneBelongs))->column('e_category_code','category_code');
        //接口请求
        foreach ($sceneBelongs as $categoryCode => $sceneBelong){
            $result = $this->http->post('sceneAdd', [
                'businessTempletId' => $eCategoryCodesColmun[$categoryCode],
                'name' => array_column($sceneBelongs[$categoryCode],'name')
            ]);
            $resArr = array_flip($result['result']);
            foreach ($evidenceScenes as &$scene){
                $scene->e_scene_code = $resArr[$scene->name];
            }
            $this->evidenceSceneModel->saveAll($evidenceScenes->toArray());
        }
        
        //据点处理
        $evidencePoints = $this->evidencePointModel->where('e_point_code','')
            ->withoutField('create_time,update_time,delete_time')
            ->select();
        
        $pointBelongs = [];
        foreach ($evidencePoints->toArray() as $point){
            if(!isset($pointBelongs[$point['scene_code']])){
                $pointBelongs[$point['scene_code']] = [];
            }
            array_push($pointBelongs[$point['scene_code']],$point);
        }
        $eSceneCodesColmun = $this->evidenceSceneModel->whereIn('scene_code',array_keys($pointBelongs))->column('e_scene_code','scene_code');
        foreach ($pointBelongs as $sceneCode => $pointBelong){
            $result = $this->http->post('segAdd', [
                'sceneTempletId' => $eSceneCodesColmun[$sceneCode],
                'name' => array_column($pointBelongs[$sceneCode],'name')
            ]);
            $this->evidencePointModel->saveAll($evidencePoints->toArray());
        }
        //据点属性
        $points = $this->evidencePointModel->select();
        foreach ($points as &$point){
            //设置据点属性
//            if($point['point_code'] == 'taskSubmit'){
//                p($point->e_point_code,$point['property']);
//            }
            $result = $this->http->post('segPropAdd',[
                'segmentTempletId'  =>  $point->e_point_code,
                'properties'    =>  $point['property']
            ]);
            
        }
    }

    /**
     * @param $pointCode
     * @return mixed
     */
    public function getPointEviCode($pointCode)
    {
        $ePointCode = $this->evidencePointModel->where('point_code',$pointCode)->value('e_point_code');
        return $ePointCode;
    }


    public function setSceneRow($sceneCode)
    {
        $this->pointRow = $this->getSceneRow($sceneCode);
        return $this;
    }

    public function getSceneRow($sceneCode)
    {
        $sceneRow = $this->evidenceSceneModel->where('scene_code',$sceneCode)->find();
        return $sceneRow->toArray();
    }

    public function setPointRow($ePointCode)
    {
        $this->pointRow = $this->getPointRow($ePointCode);
        return $this;
    }

    public function getPointRow($ePointCode)
    {
        $pointRow = $this->evidencePointModel->where('e_point_code',$ePointCode)->find();
        return $pointRow;
    }

    public function setCurrentChainModel($currentChainModel = null)
    {
        $this->currentChainModel = $currentChainModel;
    }

    public function getCurrentChainModel($logicUniqueCode = '')
    {
        if(!$this->currentChainModel && $logicUniqueCode){
            $this->currentChainModel = $this->evidenceChainModel->where('logic_unique_code',$logicUniqueCode)->find();
        }
        if(!$this->currentChainModel){
            throw new EviException('未找到所属证据链模型');
        }
        return $this->currentChainModel;
    }

    /**
     * @param $evResult
     * @param $propertyContent
     * @param $ePointCode
     * @param $logicData
     * @return array|Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function createChainPoint($evResult,$propertyContent,$ePointCode,$logicData)
    {
        if(!$this->pointRow){
            $this->setPointRow($ePointCode);
        }
        $pointRow = $this->pointRow;
        $evidenceChainPointModel = $this->evidenceChainPointModel->where([
            'logic_unique_code' =>  $logicData['logicUniqueCode'],
            'scene_code'    =>  $pointRow['scene_code'],
            'point_code'    =>  $pointRow['point_code']
        ])->find();
        $evResult['url'] = $evResult['url'] ?? '';
        $data = [
            'scene_code'    =>  $pointRow['scene_code'],
            'e_point_code'  =>  $pointRow['e_point_code'],
            'point_code'  =>  $pointRow['point_code'],
            'property_content'  =>   $propertyContent,
            'e_point_url'  =>   $evResult['url'],
            'e_point_evid'  =>   $evResult['evid'],
//            'logic_content' =>  $logicData['logicContent'],
            'logic_unique_code' =>  $logicData['logicUniqueCode'],
            'evidence_chain_id' =>  $this->currentChainModel['id']
        ];
        if($evidenceChainPointModel)
            $status = $evidenceChainPointModel->save($data);
        else
            $status = $evidenceChainPointModel = $this->evidenceChainPointModel->create($data);

        if(!$status){
            throw new EviException('保存证据链据点失败');
        }
        return $evidenceChainPointModel;
    }

    /**
     * @param int $chainId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getPointEviCodesForCreatEviChain($chainId = 0)
    {
        if($chainId){
            $this->currentChainModel = $this->evidenceChainModel->where('id',$chainId)->select()->toArray();
        }
        $ePointCodes = $this->evidenceChainPointModel->where('evidence_chain_id',$this->currentChainModel['id'])->field('e_point_evid,type')->select()->toArray();
        foreach ($ePointCodes as &$ePointCode){
            $ePointCode['value'] = $ePointCode['e_point_evid'];
            unset($ePointCode['e_point_evid']);
        }
        return $ePointCodes;
    }

    /**
     * @param $sceneCode
     * @param $logicUniqueCode
     * @param string $eSceneCode
     * @param string $eChainCode
     * @return Model
     */
    public function createChain($sceneCode, $logicUniqueCode, $eSceneCode = '', $eChainEvid = '')
    {
        $data['scene_code'] = $sceneCode;
        $data['logic_unique_code'] = $logicUniqueCode;
        if($eSceneCode){
            $data['e_scene_code'] = $eSceneCode;
        }
        if($eChainCode){
            $data['e_chain_evid'] = $eChainEvid;
        }
        $currentChainModel = $this->evidenceChainModel->create($data);
        if(!$this->currentChainModel){
            $this->currentChainModel = $currentChainModel;
        }
        return $this->currentChainModel;
    }

    public function updateChain($map)
    {
        $this->currentChainModel->save($map);
    }





}